package other;

import java.util.Objects;
import java.util.Random;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 重试工具类
 *
 * @author 王霄
 * @date 2024/9/5 13:35
 */
public class RetryUtil {

    /**
     * @param logic        业务逻辑，返回结果T，内部异常需要业务逻辑自行捕获，通用方法不做处理。
     * @param verify       对结果进行断言，true结束重试，false继续执行
     * @param consumer     对结果进行一次消费
     * @param retryCount   重试次数（初次执行包含在计数范围内）
     * @param defaultValue 达到最大重试次数，要返回的默认值
     * @param <T>          业务逻辑结果类型
     * @return 业务逻辑结果
     */
    public static <T> T retry(Supplier<T> logic,
                              Predicate<T> verify,
                              BiConsumer<Integer, T> consumer,
                              int retryCount,
                              T defaultValue) {
        Objects.requireNonNull(logic);
        Objects.requireNonNull(verify);
        for (int i = 1; i <= retryCount; i++) {
            T t = logic.get();
            if (consumer != null) {
                consumer.accept(i, t);
            }
            if (verify.test(t)) {
                return t;
            }
        }
        return defaultValue;
    }

    public static <T> T retry(Supplier<T> logic,
                              Predicate<T> verify,
                              int retryCount) {
        return retry(logic, verify, null, retryCount, null);
    }

    public static <T> T retry(Supplier<T> logic,
                              Predicate<T> verify,
                              int retryCount,
                              T defaultValue) {
        return retry(logic, verify, null, retryCount, defaultValue);
    }

    public static <T> T retry(Supplier<T> logic,
                              Predicate<T> verify,
                              BiConsumer<Integer, T> consumer,
                              int retryCount) {
        return retry(logic, verify, consumer, retryCount, null);
    }

    public static void main(String[] args) {
        Integer result = retry(() -> new Random().nextInt(5),
                x -> x == 3,
                (i, r) -> System.out.printf("第%s次重试结果：%s%n", i,r),
                100);
        System.out.println("执行结束，结果：" + result);
    }

}
